<?php
/*
* Kusht Mud.
* ----
* The MIT License
* Copyright (c) 2010 Andrew Tutt
* ----
*/

/* World Class
*
*
* Govern's Worldwide Game State Information (Dynamic)
* Including:
* :: Who's Logged In
* :: The list of game rooms
*/


class World {
	public static $char_list = array();
	public static $item_list = array();
	public static $room_list = array();
	
	// Libraries Loaded at startup (each of these contains templates used for the game)
	public static $items			= array();		// An array of item TEMPLATEs
	public static $liquids			= array();
	public static $affects 			= array(); 		// Holds all the game's possible affects (loaded into database, easily extended);
	public static $spells 			= array();		// Holds all the game's possible spells (see above);
	public static $special_attacks	= array(); 		// For Special Attacks
	
	// Listeners
	
	// Meta Information
	public static $chatrooms		= array();
	
	/* We use an EXTREMELY efficient checking model, wherein we use sorted information to 
	*  significantly reduce the number of automated checks that are performed in the game.
	*  we do this by governing lots of data here. For instance, affects are only checked
	*  if they are actually affecting something in the game, and they are checked from
	*  closest to expiration to farthest, breaking the check when the next item in the list is unexpired.
	*  We use this same method repeatedly game-wide. */
	public static function Update() {
		// Check all Affects for timeouts
		foreach(World::$affects as $affect) {
			if(!key($affect->affected)) { break; }
			if(key($affect->affected) > microtime(1)) { break; }
			$affect->expire();
		}
		
		StateMngr::handleTimedListeners(array(TIME=>microtime(1)));
		
	}
	
	public static function get_char_world($queryinguser,$targetstr) {
		$userinroom = $queryinguser->in_room()->get_char($queryinguser, $targetstr);
		if ($userinroom) {
			return $userinroom;
		}
		foreach(World::$char_list as $char) {
			if (stripos($char->name,$targetstr)!==FALSE) { return $char; }
		}
		return false;
	}
	
	public static function add_char($user) {
		World::$char_list += array($user->copy_id=>$user);
		// Throw off a trigger to update the global "who" list
		World::whoisUpdate();
	}
	
	public static function rmv_char($user) {
		$user->save();
		unset(World::$char_list[$user->copy_id]);
		// Throw off a trigger to update the global "who" list
		World::whoisUpdate();
		
		// Remove from chatrooms
		foreach(World::$chatrooms as $e) {
			$e->rmv_char($user);
		}
	}
	
	public static function whoisUpdate() {
		foreach(World::$char_list as $person) {
			ClientHandler::whois($person);
		}
	}
	
	// LOW LEVEL FUNCTIONS (USED FOR SORTING)
	
	function sortAffects() {
		usort(World::$affects,"World::compareAffectsExpirations");
	}
	
	function compareAffectsExpirations($a,$b) {
		if(current($a->affected)) { $a = key($a->affected); }
		else { return 1; }
		if(current($b->affected)) { $b = key($b->affected); }
		else { return -1; }
		return ($a < $b) ? -1 : 1;
	}
	
	function sortRooms() {
		reset(World::$room_list);
		// Right now, we no longer sort rooms
		//usort(World::$room_list,"World::compareObjIntervals");
	}
	
	/*function compareObjIntervals($a,$b) {
		if($a->timed_script_code == "") { return 1; }
		if($b->timed_script_code == "") { return -1; }
		return ($a->interval_length < $b->interval_length) ? -1 : 1;		
	}*/
	
	/* SHAMEFUL BUT NECESSARY FUNCTIONS THAT BELONG NOWHERE ELSE */
	
	public static function orderExits(&$exitsarray) {
		usort($exitsarray,"World::compareExitTypes");
	}
	
	// A nod to reality... these are the cardinals
	public static function compareExitTypes($a,$b) {
		if($a->name == "north") return -1;
		if($b->name == "north") return 1;
		if($a->name == "south") return -1;
		if($b->name == "south") return 1;
		if($a->name == "east") return -1;
		if($b->name == "east") return 1;
		if($a->name == "west") return -1;
		if($b->name == "west") return 1;
		if($a->name == "up") return -1;
		if($b->name == "up") return 1;
		if($a->name == "down") return -1;
		if($b->name == "down") return 1;
		// Always last
		if($a->name == "leave") return 1;
		if($b->name == "leave") return -1;
		return 0;
	}
	
}

?>